namespace cxxcall
{

bool cb_data::_Reg_struct_ret ()
{
  if (this->rsize <= 16)
    return (true);

  this->raddr = this->structaddr;
  return (false);
}

void* cb_data::xarg (size_t size, size_t align, bool integral, bool)
{
  if (this->ianum + ((size + WSIZE - 1) / WSIZE) <= IARG_NUM)
    {
      void *ret = &this->iargs[this->ianum];
      this->ianum += (size + WSIZE - 1) / WSIZE;
      return (ret);
    }

  void *ret = (void *)this->curr;
  this->curr += cb_data::arg_size (size);
  return (ret);
}

static float
fltarg_val (av_base::fltarg& f, float)
{
  return (f.f);
}

static double
fltarg_val (av_base::fltarg& f, double)
{
  return (f.d);
}

static long double
fltarg_val (av_base::fltarg& f, long double)
{
  return (f.ld);
}

template <class T>
static T farg_val (cb_data& self, size_t off)
{
  if (self.fanum < av_base::FARG_NUM)
    return (fltarg_val (self.fargs[self.fanum++], T ()));

  void *ret = (void *)self.curr;
  self.curr += off;
  return (*(T *)ret);
}

float cb_data::arg_f ()
{
  return (farg_val<float> (*this, WSIZE));
}

double cb_data::arg_d ()
{
  return (farg_val<double> (*this, WSIZE));
}

long double cb_data::arg_ld ()
{
  return (farg_val<long double> (*this, sizeof (long double)));
}

} // namespace cxxcall
